﻿using Inspire.Classes.Business;
using Inspire.Classes.Common;
using Inspire.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Inspire.Entities
{
    public partial class CustomFieldType : IDataErrorInfo, IValidation
    {
        /// <summary>
        /// Get a reference to the CustomFieldBusiness class.
        /// </summary>
        private CustomFieldBusiness _customFieldBusiness = CustomFieldBusiness.GetCustomFieldBusiness();

        /// <summary>
        /// Provide a user-friendly label for the Custom Field Category.
        /// </summary>
        public string CategoryLabel
        {
            get
            {
                if (Constants.CustomFieldCategoryLabelLookup.ContainsKey(this.Category))
                {
                    return (string)Constants.CustomFieldCategoryLabelLookup[this.Category];
                }
                return "";
            }
        }

        #region IDataErrorInfo Implementation
        protected Dictionary<string, string> _errors = new Dictionary<string, string>();

        public string Error
        {
            get
            {
                return String.Empty;
            }
        }

        public string this[string columnName]
        {
            get
            {
                if (_errors.ContainsKey(columnName))
                {
                    return _errors[columnName];
                }
                return String.Empty;
            }
        }
        #endregion

        #region Partial Implementation of Property Event Handlers

        partial void OnNameChanging(string value)
        {
            string errorMessage = this.ValidateName(value);

            if (errorMessage.Length > 0)
            {
                Console.Out.WriteLine("Error with Name!");
                this._errors.Add("Name", errorMessage);
                return;
            }

            this._errors.Remove("Name");
        }

        partial void OnTypeChanging(string value)
        {
            string errorMessage = this.ValidateType(value);

            if (errorMessage.Length > 0)
            {
                this._errors.Add("Type", value);
                return;
            }

            this._errors.Remove("Type");
        }

        partial void OnCategoryChanging(string value)
        {
            string errorMessage = this.ValidateCategory(value);

            if (errorMessage.Length > 0)
            {
                this._errors.Add("Category", errorMessage);
                return;
            }

            this._errors.Remove("Category");
        }

        #endregion

        #region IValidation Implementation
        /// <summary>
        /// Returns a validation message for Name.
        /// </summary>
        /// <param name="value">The value to be validated.</param>
        /// <returns>Validation message.</returns>
        protected string ValidateName(string value)
        {
            if (value == null || value.Trim().Length < 1)
            {
                return "Name cannot be blank.";
            }

            return String.Empty;
        }

        /// <summary>
        /// Returns a validation message for Type.
        /// </summary>
        /// <param name="value">The value to be validated.</param>
        /// <returns>Validation message.</returns>
        protected string ValidateType(string value)
        {
            if (value == null || value.Trim().Length < 1)
            {
                return "A Type must be selected.";
            }
            return String.Empty;
        }

        /// <summary>
        /// Returns a validation message for Category.
        /// </summary>
        /// <param name="value">The value to be validated.</param>
        /// <returns>Validation message.</returns>
        protected string ValidateCategory(string value)
        {
            if (value == null || !(Constants.CustomFieldCategoryLabelLookup.ContainsKey(value)))
            {
                return "A Category must be selected.";
            }
            return String.Empty;
        }

        /// <summary>
        /// Validate all fields
        /// </summary>
        /// <returns>bool True if no errors were found; false, otherwise.</returns>
        public bool Validate()
        {
            // Initialize isValidated to true
            bool isValidated = true;

            // Clear any pre-existing errors
            this._errors.Clear();

            // Store each message of validation
            string message;

            #region Validate fields and record the messages in _errors

            // Name
            message = ValidateName(this.Name);
            if (message.Length > 0)
            {
                this._errors.Add("Name", message);
                isValidated = false;
            }
            else
            {
                // Name Uniqueness Check
                CustomFieldType result = this._customFieldBusiness.GetCustomFieldType(this.Category, this.Name);
                if (result != null && result.Id != this.Id)
                {
                    this._errors.Add("Name", "The name provided is not unique to this custom field category. Please choose either another category or provide a unique name.");
                    isValidated = false;
                }
            }

            // Type
            message = ValidateType(this.Type);
            if (message.Length > 0)
            {
                this._errors.Add("Type", message);
                isValidated = false;
            }

            // Category
            message = ValidateCategory(this.Category);
            if (message.Length > 0)
            {
                this._errors.Add("Category", message);
                isValidated = false;
            }

            #endregion

            return isValidated;
        }

        /// <summary>
        /// Get all the errors found after the Validate() method is ran
        /// </summary>
        /// <returns>string[] of all message messages</returns>
        public string[] GetAllErrors()
        {
            string[] allErrors = new string[this._errors.Count];

            int counter = 0;
            foreach (KeyValuePair<string, string> nextError in this._errors)
            {
                allErrors[counter] = nextError.Value;
                counter++;
            }

            return allErrors;
        }
        #endregion

        /// <summary>
        /// Perform a shallow copy of this object and return the copy.
        /// </summary>
        /// <returns>A shallow copy of this object.</returns>
        public CustomFieldType ShallowCopy()
        {
            return (CustomFieldType)this.MemberwiseClone();
        }
    }
}
